package com.wdb007.venus.svc.biz.book;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wdb007.venus.svc.biz.manager.ConfigInfoManager;
import com.wdb007.venus.svc.biz.utils.MapUtils;
import com.wdb007.venus.svc.dal.banner.dao.BannerImgDAO;
import com.wdb007.venus.svc.dal.banner.model.BannerImgDO;
import com.wdb007.venus.svc.dal.book.dao.BookEntityDAO;
import com.wdb007.venus.svc.dal.book.dao.BookGridDAO;
import com.wdb007.venus.svc.dal.book.dao.BookShelfDAO;
import com.wdb007.venus.svc.dal.book.model.BookGridDO;
import com.wdb007.venus.svc.dal.book.model.BookShelfDO;
import com.wdb007.venus.svc.dal.book.model.BookShelfDistanceDO;
import com.wdb007.venus.svc.dal.book.model.BookShelfPageDO;
import com.wdb007.venus.svc.dal.bs.dao.BsHeartbeatLogDAO;
import com.wdb007.venus.svc.dal.bs.model.BsHeartbeatLogDO;
import com.wdb007.venus.svc.dal.qrcode.dao.QrCodeCurrentInfoDAO;
import com.wdb007.venus.svc.dal.qrcode.model.QrCodeCurrentInfoDO;
import com.wdb007.venus.svc.facade.BookShelfService;
import com.wdb007.venus.svc.facade.BsAlarmService;
import com.wdb007.venus.svc.facade.banner.model.BannerImgDTO;
import com.wdb007.venus.svc.facade.book.model.BookShelfDTO;
import com.wdb007.venus.svc.facade.book.model.BookShelfLocationDTO;
import com.wdb007.venus.svc.facade.book.model.BookShelfPageDTO;
import com.wdb007.venus.svc.facade.bs.model.BsAlarmDTO;
import com.wdb007.venus.svc.facade.constant.BizConstants;
import com.wdb007.venus.svc.facade.constant.RspCodeEnum;
import com.wdb007.venus.svc.facade.exception.BizException;

@Service("bookShelfSerivce")
public class BookShelfServiceImpl implements BookShelfService {
	
	private static final Logger logger = LoggerFactory.getLogger(BookShelfServiceImpl.class);
	
	@Autowired
	private BookShelfDAO bookShelfDAO;
	@Autowired
	private BookEntityDAO bookEntityDAO;
	@Autowired
	private BannerImgDAO bannerImgDAO;
	@Autowired
	private QrCodeCurrentInfoDAO qrCodeCurrentInfoDAO;
	@Autowired
	private BsHeartbeatLogDAO bsHeartbeatLogDAO;
	@Autowired
	private BookGridDAO bookGridDAO;
	@Autowired
	private ConfigInfoManager configInfoManager;	
	
	@Autowired
	private BsAlarmService bsAlarmService;
	
	@Override
	public int insert(BookShelfDTO bookShelf)  throws BizException{
		
		BookShelfDO bookShelfDO = new BookShelfDO();
		BeanUtils.copyProperties(bookShelf, bookShelfDO);
		int result = bookShelfDAO.insert(bookShelfDO);
		return result;
	}

	@Override
	public int update(BookShelfDTO bookShelf)  throws BizException{
		
		BookShelfDO bookShelfDO = new BookShelfDO();
		BeanUtils.copyProperties(bookShelf, bookShelfDO);
		int result = bookShelfDAO.update(bookShelfDO);
		return result;
	}

	@Override
	public BookShelfDTO get(String code)  throws BizException{
		if(code.trim().length() == 6) {
			QrCodeCurrentInfoDO currentInfoDO = qrCodeCurrentInfoDAO.getByShortKey(code);
			if(null == currentInfoDO) {
				throw new BizException(RspCodeEnum.QRCODE_ANALYSIS_IS_WRONG);
			}
			code = currentInfoDO.getBookcaseId();
		}
		
		BookShelfDO bookShelfDO = bookShelfDAO.get(code);
		BookShelfDTO bookShelf = new BookShelfDTO();
		BeanUtils.copyProperties(bookShelfDO, bookShelf);
		return bookShelf;
	}

	@Override
	public List<BookShelfDTO> list()  throws BizException{
		
		List<BookShelfDO> list = bookShelfDAO.list();
		if(CollectionUtils.isEmpty(list))
			return null;
		List<BookShelfDTO> dtoList = new ArrayList<BookShelfDTO>(list.size());
		for(BookShelfDO bookShelfDO : list){
			BookShelfDTO bookShelf = new BookShelfDTO();
			BeanUtils.copyProperties(bookShelfDO, bookShelf);
			dtoList.add(bookShelf);
		}
		return dtoList;
	}

	@Override
	public int remove(String code)  throws BizException{
		return bookShelfDAO.remove(code);
	}

	@Override
	public List<BookShelfDTO> listByLocation(BookShelfDTO bookShelf, Integer mapType)  throws BizException{
		BookShelfDO bookShelfDO = new BookShelfDO();
		bookShelfDO.setLatitude(bookShelf.getLatitude());
		bookShelfDO.setLongitude(bookShelf.getLongitude());
		List<BookShelfDO> list = null ;
		if( 0 == mapType) {
			list = bookShelfDAO.listByLocation(bookShelfDO);
		}else if(null == mapType || 1 == mapType) {	//默认传递火星坐标系
			list = bookShelfDAO.listByLocationGcj02(bookShelfDO);
		}else if(2 == mapType) {
			list = bookShelfDAO.listByLocationBd09(bookShelfDO);
		}
		if(CollectionUtils.isEmpty(list))
			return null;
		List<BookShelfDTO> dtoList = new ArrayList<BookShelfDTO>(list.size());
		for(BookShelfDO bookShelfDO2 : list){
			BookShelfDTO bookShelf2 = new BookShelfDTO();
			
			BeanUtils.copyProperties(bookShelfDO2, bookShelf2);
			if( 0 == mapType) {
				bookShelf2.setLatitude(bookShelfDO2.getLatitude());
				bookShelfDO2.setLongitude(bookShelfDO2.getLongitude());
			}else if(null == mapType || 1 == mapType) {	//默认传递火星坐标系
				bookShelf2.setLatitude(bookShelfDO2.getGcj02Latitude());
				bookShelfDO2.setLongitude(bookShelfDO2.getGcj02Longitude());				
			}else if(2 == mapType) {
				bookShelf2.setLatitude(bookShelfDO2.getBd09Latitude());
				bookShelfDO2.setLongitude(bookShelfDO2.getBd09Longitude());				
			}
			
			dtoList.add(bookShelf2);
		}
		
		return dtoList;
	}

	@Override
	public BookShelfDTO getNearest(BookShelfDTO bookShelf, Integer mapType) throws BizException {
		
		String shelfCode = bookShelf.getCode();
		BookShelfDO result = null ;
		
		if(!ObjectUtils.isEmpty(shelfCode)) {
			result = bookShelfDAO.get(shelfCode);
		}else if(!ObjectUtils.isEmpty(bookShelf.getLatitude()) && !ObjectUtils.isEmpty(bookShelf.getLongitude())){
			BookShelfDO query = new BookShelfDO();
			query.setLatitude(bookShelf.getLatitude());
			query.setLongitude(bookShelf.getLongitude());
			result = bookShelfDAO.getNearestShelf(query);
		}else {
			shelfCode = configInfoManager.getValue("default_shelf_code");
			result = bookShelfDAO.get(shelfCode);
		}
		if(result == null)
			return null ;
		result.setAddress(result.getArea());
		
		BookShelfDTO dto = new BookShelfDTO();
		BeanUtils.copyProperties(result, dto);
		return dto;
	}

	@Override
	public List<BannerImgDTO> getBannerImgList() throws BizException {
	
		List<BannerImgDO> imgUrls = bannerImgDAO.getImgUrl();
		List<BannerImgDTO> list = new ArrayList<BannerImgDTO>();
		
		for(BannerImgDO url: imgUrls) {
			BannerImgDTO dto = new BannerImgDTO();
			BeanUtils.copyProperties(url, dto);
			dto.setImgurl(configInfoManager.getImgurl(url.getImgurl())); 
			list.add(dto);
		}
		return list;
	}

	@Override
	public BookShelfPageDTO queryshelfList(BookShelfDTO bookShelf, Integer mapType, Integer offset, Integer pagesize) throws BizException {
		BookShelfPageDTO pageDTO = new BookShelfPageDTO();
		BookShelfPageDO query = new BookShelfPageDO();
		query.setLatitude(bookShelf.getLatitude());
		query.setLongitude(bookShelf.getLongitude());
		query.setPagesize(pagesize);
		query.setOffset(offset);
		int count = bookShelfDAO.countSortByDistance(query);
		pageDTO.setTotalcount(count);
		List<BookShelfDistanceDO> list = bookShelfDAO.listSortByDistance(query);
		if(CollectionUtils.isEmpty(list))
			return pageDTO;
		List<BookShelfLocationDTO> dtoList = new ArrayList<BookShelfLocationDTO>();
		for(BookShelfDistanceDO bs : list) {
			BookShelfLocationDTO dto = new BookShelfLocationDTO();
			dto.setAddress(bs.getAddress());
			dto.setArea(bs.getArea());
			dto.setBookshelf_code(bs.getCode());
			dto.setLatitude(bs.getLatitude());
			dto.setLongitude(bs.getLongitude());
			dto.setStored_count(bookEntityDAO.queryStoredCount(bs.getCode()));
//			String distance = MapUtils.getDistance(bs.getLatitude(), bs.getLongitude(), bookShelf.getLatitude(), bookShelf.getLongitude());
			String distance = MapUtils.getDistance(bs.getDis());
			dto.setDistance(distance);
			dtoList.add(dto);
		}
		pageDTO.setList(dtoList);
		return pageDTO;
	}

	@Override
	public void heartBeat(JSONObject data) {
		String bookcaseId = data.getString("id");
		logger.info("书柜编号:[{}]", bookcaseId);
		JSONArray gs = data.getJSONArray("gs");
		JSONArray ls = data.getJSONArray("ls");
		JSONArray zs = data.getJSONArray("zs");
		Integer uvFlag = Integer.valueOf(data.getString("zf"));
		//保存数据
		BsHeartbeatLogDO bsHeartBeatLog = bsHeartbeatLogDAO.get(bookcaseId);
		if(null == bsHeartBeatLog) {
			bsHeartBeatLog = new BsHeartbeatLogDO();
			bsHeartBeatLog.setBookcaseId(bookcaseId);
			bsHeartBeatLog.setGridStatus(gs.toJSONString());
			bsHeartBeatLog.setErrFlag(Integer.valueOf(data.getString("e")));
			bsHeartBeatLog.setLedStatus(ls.toJSONString());
			bsHeartBeatLog.setTs(new Date(data.getLong("ts")));
			bsHeartBeatLog.setUvFlag(Integer.valueOf(data.getString("zf")));
			bsHeartBeatLog.setUvStatus(zs.toJSONString());
			bsHeartBeatLog.setVer(data.getString("ver"));
			bsHeartbeatLogDAO.insert(bsHeartBeatLog);
		}else {
			bsHeartBeatLog.setGridStatus(data.getJSONArray("gs").toJSONString());
			bsHeartBeatLog.setErrFlag(Integer.valueOf(data.getString("e")));
			bsHeartBeatLog.setLedStatus(data.getString("ls"));
			bsHeartBeatLog.setTs(new Date(data.getLong("ts")));
			bsHeartBeatLog.setUvFlag(Integer.valueOf(data.getString("zf")));
			bsHeartBeatLog.setUvStatus(data.getString("ss"));
			bsHeartBeatLog.setVer(data.getString("ver"));
			bsHeartbeatLogDAO.update(bsHeartBeatLog);
		}
		
		//2.判断书格各种状态
		List<BookGridDO> gridList = bookGridDAO.getBookGridList(bookcaseId);
		for(int i=0; i<gridList.size(); i++) {
			BookGridDO bookGrid = gridList.get(i);
			//判断书格状态
			int lockStatus = bookGrid.getLockStatus();
			int s = Integer.valueOf((String)gs.get(i));
			if((s==0 && lockStatus==1) 		//上报的书格状态为关闭，但是数据库状态为打开状态
					|| (s==1 && lockStatus != 1)//上报的书格状态为打开，但是数据库状态为非打开状态
			  ) {
				insertAlarm(bookGrid.getBookgridCode(), BizConstants.BS_ALARM_TYPE_0);
			}
			//判断紫外线
			int uvStatus = Integer.valueOf((String)zs.get(i));
			if((1 == uvFlag && uvStatus == 0) || (0 == uvFlag && uvStatus == 1)) {
				insertAlarm(bookGrid.getBookgridCode(), BizConstants.BS_ALARM_TYPE_1);
			}
			//判断LED灯
			int ledStatus = Integer.valueOf((String)ls.get(i));
			if(1 == lockStatus && ledStatus == 0) {
				insertAlarm(bookGrid.getBookgridCode(), BizConstants.BS_ALARM_TYPE_2);
			}
		}
		
		//3.判断书柜版本
		String ver = bookShelfDAO.getVersion(bookcaseId);
		if(!ver.equalsIgnoreCase(data.getString("ver"))) {
			insertAlarm(bookcaseId+"01", BizConstants.BS_ALARM_TYPE_3);
		}
	}
	
	private void insertAlarm(String gridCode, Integer alarmType){
		
		BsAlarmDTO bsAlarm = new BsAlarmDTO();
		String alarmContent = "";
		if(alarmType == BizConstants.BS_ALARM_TYPE_0) {	//书格报警
			alarmContent ="书格["+gridCode+"]门锁状态异常，请及时处理。";
		}else if(alarmType == BizConstants.BS_ALARM_TYPE_1) {	//紫外线报警
			alarmContent ="书格["+gridCode+"]紫外线在异常，请及时处理。";
		}else if(alarmType == BizConstants.BS_ALARM_TYPE_2) {	//LED报警
			alarmContent ="书格["+gridCode+"]LED在异常，请及时处理。";
		}else if(alarmType == BizConstants.BS_ALARM_TYPE_3) {	//软件版本不一致报警
			//FIXME 软件版本不一致时，数据如何存储？书格编号如何存？
			String bookcaseId = gridCode.substring(0, 10);
			alarmContent = "书柜["+bookcaseId+"]版本不一致，请及时更新";
		}else if(alarmType == BizConstants.BS_ALARM_TYPE_4) {	//网络异常报警
			//FIXME
		}
		bsAlarm.setAlarmContent(alarmContent);
		bsAlarm.setBookgridCode(gridCode);
		bsAlarm.setAlarmType(alarmType);
		try {
			bsAlarmService.saveBsAlarm(bsAlarm);
		} catch (BizException e) {
			logger.error("保存报警信息异常", e);
		}
			
	}

	@Override
	public String getVersion(String bookcaseId) throws BizException {
		
		String version = bookShelfDAO.getVersion(bookcaseId);
		
		return version;
	}

	@Override
	public String getPolicyInfo(String bookcaseId) throws BizException {
		
		BookShelfDO bookshelf = bookShelfDAO.get(bookcaseId);
		if(null == bookshelf) {
			logger.info("根据书柜编号[{}]查询不到书柜信息，使用默认配置", bookcaseId);
			return policiesIssued();
		}
		return bookshelf.getPolicyRule();
	}
	/**
	 * 默认下发策略
	 * @return
	 */
	private String policiesIssued() {
		
		Map<String, Object> innerMap = new HashMap<String, Object>();
		String statusCheck = configInfoManager.getValue("statusCheck");
		String bookCheck = configInfoManager.getValue("bookCheck");
		String[] statusCheckArr = statusCheck.split(",");
		List<String> statusList = Arrays.asList(statusCheckArr);
		String[] bookCheckArr = bookCheck.split(",");
		List<String> checkList = Arrays.asList(bookCheckArr);
		innerMap.put("interval", Integer.valueOf(configInfoManager.getValue("interval")));
		innerMap.put("statusCheck", statusList);
		innerMap.put("bookCheck", checkList);
		innerMap.put("reserve", configInfoManager.getValue("reserve"));
		
		String uvlamp_start = configInfoManager.getValue("uvlamp_start");
		String[] uvlamp_startArr = uvlamp_start.split(",");
		List<String> uvlamp_startList = Arrays.asList(uvlamp_startArr);	
		
		String led_start_end = configInfoManager.getValue("led_start_end");
		String[] led_start_endArr = led_start_end.split(",");
		List<String> led_start_endArrList = Arrays.asList(led_start_endArr);	
		
		innerMap.put("uvlamp_start", uvlamp_startList);
		innerMap.put("led_start_end", led_start_endArrList);
		innerMap.put("uvlamp_keep", Integer.valueOf(configInfoManager.getValue("uvlamp_keep")));
		return JSON.toJSONString(innerMap);
	}

	@Override
	public String getModel(String bookcaseId) throws BizException {
		BookShelfDO bookShelf = bookShelfDAO.get(bookcaseId);
		if(null == bookShelf) {
			return null;
		}
		return bookShelf.getModel();
	}
}
